package com.jtcoding.distributedlock.service.impl;

import com.jtcoding.distributedlock.commons.RedisLock;
import com.jtcoding.distributedlock.dao.OrderDao;
import com.jtcoding.distributedlock.dao.SeckillDao;
import com.jtcoding.distributedlock.model.Order;
import com.jtcoding.distributedlock.model.Seckill;
import com.jtcoding.distributedlock.service.SeckillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author jason.tang
 * @Date 2020/01/23 21:29
 * @Desc
 */

@Service("seckillService")
public class SeckillServiceImpl implements SeckillService {

    @Autowired
    private SeckillDao seckillDao;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private RedisLock redisLock;

    @Transactional
    @Override
    public Seckill double11GoodsSeckill(Integer seckillNum) {
        int count = 2;

        String lockValue = String.valueOf(System.currentTimeMillis());
        boolean lock = redisLock.lock(seckillNum.toString(), lockValue);
        if (!lock) {
            throw new RuntimeException("Sorry, too many people at present, please try again later...");
        }

        Seckill seckill = seckillDao.getSeckillDetail(seckillNum);
        Integer sold = seckill.getSold();
        Integer total = seckill.getTotal();
        int currentSold = count + sold;
        if (total - sold <= 0) {
            throw new RuntimeException("Sorry, seckill end...");
        }

        if (currentSold > total) {
            throw new RuntimeException("Sorry, insufficient stock...");
        }

        Order orderBO = Order.builder()
                .goodsNum(seckill.getGoodsNum())
                .goodsCount(count)
                .orderStatus("Wait Pay")
                .build();

        try {
            int rtn = seckillDao.updateSeckillSold(seckillNum, currentSold);
            if (rtn == 0) {
                throw new RuntimeException("Sorry, update seckill sold error...");
            }

            rtn = orderDao.addOrder(orderBO);
            if (rtn == 0) {
                throw new RuntimeException("Sorry, add order book error...");
            }
        }
        catch (Exception e) {
            throw new RuntimeException("Sorry, system error...");
        }
        finally {
            redisLock.unlock(seckillNum.toString(), lockValue);
        }

        return seckill;
    }
}
